Trò chơi đua xe động vật trong UNITY Engine
- FlowLayoutGroup.cs
- Layout /
- AnimalRacing /
- Scripts /
- Assets /
- project /
2 /// Sourced from - http://forum.unity3d.com/threads/flowlayoutgroup.296709/
3 /// Example http://forum.unity3d.com/threads/flowlayoutgroup.296709/
4 /// Update by Martin Sharkbomb - http://forum.unity3d.com/threads/flowlayoutgroup.296709/#post-1977028
5 /// Last item alignment fix by Vicente Russo - https://bitbucket.org/ddreaper/unity-ui-extensions/issues/22/flow-layout-group-align
6
7 using System.Collections.Generic;
8
9 namespace UnityEngine.UI.Extensions
10 {
11 /// <summary>
12 /// Layout Group controller that arranges children in rows, fitting as many on a line until total width exceeds parent bounds
13 /// </summary>
14 [AddComponentMenu("Layout/Extensions/Flow Layout Group")]
15 public class FlowLayoutGroup : LayoutGroup
16 {
17 public float SpacingX = 0f;
18 public float SpacingY = 0f;
19 public bool ExpandHorizontalSpacing = false;
20
21 public bool ChildForceExpandWidth = false;
22 public bool ChildForceExpandHeight = false;
23
24 private float _layoutHeight;
25
26 public override void CalculateLayoutInputHorizontal()
27 {
28
29 base.CalculateLayoutInputHorizontal();
30
31 var minWidth = GetGreatestMinimumChildWidth() + padding.left + padding.right;
32
33 SetLayoutInputForAxis(minWidth, -1, -1, 0);
34
35 }
36
37 public override void SetLayoutHorizontal()
38 {
39 SetLayout(rectTransform.rect.width, 0, false);
40 }
41
42 public override void SetLayoutVertical()
43 {
44 SetLayout(rectTransform.rect.width, 1, false);
45 }
46
47 public override void CalculateLayoutInputVertical()
48 {
49 _layoutHeight = SetLayout(rectTransform.rect.width, 1, true);
50 }
51
52 protected bool IsCenterAlign
53 {
54 get
55 {
56 return childAlignment == TextAnchor.LowerCenter || childAlignment == TextAnchor.MiddleCenter ||
57 childAlignment == TextAnchor.UpperCenter;
58 }
59 }
60
61 protected bool IsRightAlign
62 {
63 get
64 {
65 return childAlignment == TextAnchor.LowerRight || childAlignment == TextAnchor.MiddleRight ||
66 childAlignment == TextAnchor.UpperRight;
67 }
68 }
69
70 protected bool IsMiddleAlign
71 {
72 get
73 {
74 return childAlignment == TextAnchor.MiddleLeft || childAlignment == TextAnchor.MiddleRight ||
75 childAlignment == TextAnchor.MiddleCenter;
76 }
77 }
78
79 protected bool IsLowerAlign
80 {
81 get
82 {
83 return childAlignment == TextAnchor.LowerLeft || childAlignment == TextAnchor.LowerRight ||
84 childAlignment == TextAnchor.LowerCenter;
85 }
86 }
87
88 /// <summary>
89 /// Holds the rects that will make up the current row being processed
90 /// </summary>
91 private readonly IList<RectTransform> _rowList = new List<RectTransform>();
92
93 /// <summary>
94 /// Main layout method
95 /// </summary>
96 /// <param name="width">Width to calculate the layout with</param>
97 /// <param name="axis">0 for horizontal axis, 1 for vertical</param>
98 /// <param name="layoutInput">If true, sets the layout input for the axis. If false, sets child position for axis</param>
99 public float SetLayout(float width, int axis, bool layoutInput)
100 {
101 var groupHeight = rectTransform.rect.height;
102
103 // Width that is available after padding is subtracted
104 var workingWidth = rectTransform.rect.width - padding.left - padding.right;
105
106 // Accumulates the total height of the rows, including spacing and padding.
107 var yOffset = IsLowerAlign ? (float)padding.bottom : (float)padding.top;
108
109 var currentRowWidth = 0f;
110 var currentRowHeight = 0f;
111
112 for (var i = 0; i < rectChildren.Count; i++) {
113
114 // LowerAlign works from back to front
115 var index = IsLowerAlign ? rectChildren.Count - 1 - i : i;
116
117 var child = rectChildren[index];
118
119 var childWidth = LayoutUtility.GetPreferredSize(child, 0);
120 var childHeight = LayoutUtility.GetPreferredSize(child, 1);
121
122 // Max child width is layout group width - padding
123 childWidth = Mathf.Min(childWidth, workingWidth);
124
125 // If adding this element would exceed the bounds of the row,
126 // go to a new line after processing the current row
127 if (currentRowWidth + childWidth > workingWidth) {
128
129 currentRowWidth -= SpacingX;
130
131 // Process current row elements positioning
132 if (!layoutInput) {
133
134 var h = CalculateRowVerticalOffset(groupHeight, yOffset, currentRowHeight);
135 LayoutRow(_rowList, currentRowWidth, currentRowHeight, workingWidth, padding.left, h, axis);
136
137 }
138
139 // Clear existing row
140 _rowList.Clear();
141
142 // Add the current row height to total height accumulator, and reset to 0 for the next row
143 yOffset += currentRowHeight;
144 yOffset += SpacingY;
145
146 currentRowHeight = 0;
147 currentRowWidth = 0;
148
149 }
150
151 currentRowWidth += childWidth;
152 _rowList.Add(child);
153
154 // We need the largest element height to determine the starting position of the next line
155 if (childHeight > currentRowHeight) {
156 currentRowHeight = childHeight;
157 }
158
159 // Don't do this for the last one
160 if (i < rectChildren.Count - 1 )
161 currentRowWidth += SpacingX;
162 }
163
164 if (!layoutInput) {
165 var h = CalculateRowVerticalOffset(groupHeight, yOffset, currentRowHeight);
166 currentRowWidth -= SpacingX;
167 // Layout the final row
168 LayoutRow(_rowList, currentRowWidth, currentRowHeight, workingWidth - (_rowList.Count > 1 ? SpacingX : 0), padding.left, h, axis);
169 }
170
171 _rowList.Clear();
172
173 // Add the last rows height to the height accumulator
174 yOffset += currentRowHeight;
175 yOffset += IsLowerAlign ? padding.top : padding.bottom;
176
177 if (layoutInput) {
178
179 if(axis == 1)
180 SetLayoutInputForAxis(yOffset, yOffset, -1, axis);
181
182 }
183
184 return yOffset;
185 }
186
187 private float CalculateRowVerticalOffset(float groupHeight, float yOffset, float currentRowHeight)
188 {
189 float h;
190
191 if (IsLowerAlign) {
192 h = groupHeight - yOffset - currentRowHeight;
193 } else if (IsMiddleAlign) {
194 h = groupHeight*0.5f - _layoutHeight * 0.5f + yOffset;
195 } else {
196 h = yOffset;
197 }
198 return h;
199 }
200
201 protected void LayoutRow(IList<RectTransform> contents, float rowWidth, float rowHeight, float maxWidth, float xOffset, float yOffset, int axis)
202 {
203 var xPos = xOffset;
204
205 if (!ChildForceExpandWidth && IsCenterAlign)
206 xPos += (maxWidth - rowWidth) * 0.5f;
207 else if (!ChildForceExpandWidth && IsRightAlign)
208 xPos += (maxWidth - rowWidth);
209
210 var extraWidth = 0f;
211 var extraSpacing = 0f;
212
213 if (ChildForceExpandWidth) {
214 extraWidth = (maxWidth - rowWidth)/_rowList.Count;
215 }
216 else if (ExpandHorizontalSpacing) {
217 extraSpacing = (maxWidth - rowWidth)/(_rowList.Count - 1);
218 if (_rowList.Count > 1) {
219 if (IsCenterAlign)
220 xPos -= extraSpacing * 0.5f * (_rowList.Count - 1);
221 else if (IsRightAlign)
222 xPos -= extraSpacing * (_rowList.Count - 1);
223 }
224 }
225
226 for (var j = 0; j < _rowList.Count; j++) {
227
228 var index = IsLowerAlign ? _rowList.Count - 1 - j : j;
229
230 var rowChild = _rowList[index];
231
232 var rowChildWidth = LayoutUtility.GetPreferredSize(rowChild, 0) + extraWidth;
233 var rowChildHeight = LayoutUtility.GetPreferredSize(rowChild, 1);
234
235 if (ChildForceExpandHeight)
236 rowChildHeight = rowHeight;
237
238 rowChildWidth = Mathf.Min(rowChildWidth, maxWidth);
239
240 var yPos = yOffset;
241
242 if (IsMiddleAlign)
243 yPos += (rowHeight - rowChildHeight) * 0.5f;
244 else if (IsLowerAlign)
245 yPos += (rowHeight - rowChildHeight);
246
247 //
248 if (ExpandHorizontalSpacing && j > 0)
249 xPos += extraSpacing;
250
251 if (axis == 0)
252 SetChildAlongAxis(rowChild, 0, xPos, rowChildWidth);
253 else
254 SetChildAlongAxis(rowChild, 1, yPos, rowChildHeight);
255
256 // Don't do horizontal spacing for the last one
257 if (j < _rowList.Count - 1 )
258 xPos += rowChildWidth + SpacingX;
259 }
260 }
261
262 public float GetGreatestMinimumChildWidth()
263 {
264 var max = 0f;
265
266 for (var i = 0; i < rectChildren.Count; i++) {
267 var w = LayoutUtility.GetMinWidth(rectChildren[i]);
268
269 max = Mathf.Max(w, max);
270 }
271
272 return max;
273 }
274 }
275 }
Credit Simie
Sourced from - http:forum.unity3d.comthreadsflowlayoutgroup.296709
Example http:forum.unity3d.comthreadsflowlayoutgroup.296709
Update by Martin Sharkbomb - http:forum.unity3d.comthreadsflowlayoutgroup.296709#post-1977028
Last item alignment fix by Vicente Russo - https:bitbucket.orgddreaperunity-ui-extensionsissues22flow-layout-group-align
Layout Group controller that arranges children in rows, fitting as many on a line until total width exceeds parent bounds
Holds the rects that will make up the current row being processed
Main layout method
Width to calculate the layout with
0 for horizontal axis, 1 for vertical
If true, sets the layout input for the axis. If false, sets child position for axis
Width that is available after padding is subtracted
Accumulates the total height of the rows, including spacing and padding.
LowerAlign works from back to front
Max child width is layout group width - padding
If adding this element would exceed the bounds of the row,
go to a new line after processing the current row
Process current row elements positioning
Clear existing row
Add the current row height to total height accumulator, and reset to 0 for the next row
We need the largest element height to determine the starting position of the next line
Don't do this for the last one
Layout the final row
Add the last rows height to the height accumulator
Don't do horizontal spacing for the last one